package com.wskj.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;

/**
 * @author 胡洋
 * @describe 将请求中的参数 转换为 具体的实体类 只支持简单的POJO的类 请求中的 属性名称,必须与 实体类的属性的名称一致
 *           ,并且有无参数的构造方法 以及set方法
 * @Date 2018年3月17日上午10:25:36
 * @version 1.0
 */
public class RequestUtil {
	static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
	
	/**
	 * 将请求转化为 简单的实体的类 
	 * @param cls        实体的类型
	 * @param request    用户的请求
	 * @return   实体对象	 
	 */
	public static <T> T convertRequestToEntity(Class<T> c, HttpServletRequest request) {
		try {
			T instance = c.newInstance();
			// 获取所有的请求的 参数的name值
			Map<String, String[]> map = request.getParameterMap();
			map.forEach((k, v) -> {
				invokeFieldSetMethod(instance, k, v);
			});			
			return instance;
		} catch (InstantiationException | IllegalAccessException e) {
			//e.printStackTrace();
			return null;
		}
	}

	/**
	 * 执行字段的setter方法
	 * 
	 * @param instance
	 * @param field
	 * @param set
	 */
	private static void invokeFieldSetMethod(Object instance, String name, String[] value) {
		try {
			// 获取字段的setter方法名称
			String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
			Field field = instance.getClass().getDeclaredField(name);
			// 获取字段的setter方法
			Method getMethod = instance.getClass().getMethod(methodName, field.getType());
			// 获取字段的类型名称（不包含包名）
			String typeName = field.getType().toString().toLowerCase();
			typeName = typeName.substring(typeName.lastIndexOf(".") + 1);

			// 如果属性是数组 ......
			if (field.getType().isArray()) {
				switch (typeName) {
				case "int":
				case "integer":
					int[] arr = conventStringToInt(value);
					getMethod.invoke(instance, arr);
					break;
				case "short":
					short[] arr2 = conventStringToShort(value);
					getMethod.invoke(instance, arr2);
					break;
				case "byte":
					byte[] arr3 = conventStringToByte(value);
					getMethod.invoke(instance, arr3);
					break;
				case "long":
					long[] arr4 = conventStringToLong(value);
					getMethod.invoke(instance, arr4);
					break;
				case "float":
					float[] arr5 = conventStringToFloat(value);
					getMethod.invoke(instance, arr5);
					break;
				case "double":
					double[] arr6 = conventStringToDouble(value);
					getMethod.invoke(instance, arr6);
					break;
				case "boolean":
					boolean[] arr7 = conventStringToBoolean(value);
					getMethod.invoke(instance, arr7);
					break;
				case "date":
					Date[] arr8 = conventStringToDate(value);
					getMethod.invoke(instance, arr8);
					break;
				case "string":
					getMethod.invoke(instance, value);
					break;
				}

			} else {
				// 普通的属性以及属性的值 ......
				switch (typeName) {
				case "int":
				case "integer":
					getMethod.invoke(instance, Integer.parseInt(value[0]));
					break;
				case "short":
					getMethod.invoke(instance, Short.parseShort(value[0]));
					break;
				case "byte":
					getMethod.invoke(instance, Byte.parseByte(value[0]));
					break;
				case "long":
					getMethod.invoke(instance, Long.parseLong(value[0]));
					break;
				case "float":
					getMethod.invoke(instance, Float.parseFloat(value[0]));
					break;
				case "double":
					getMethod.invoke(instance, Double.parseDouble(value[0]));
					break;
				case "boolean":
					getMethod.invoke(instance, Boolean.parseBoolean(value[0]));
					break;
				case "date":
					getMethod.invoke(instance, format.parse(value[0]));
					break;
				case "string":
					getMethod.invoke(instance, value[0]);
					break;
				}
			}
		} catch (Exception ex) {
			// ex.printStackTrace();
		}
	}

	/**
	 * 将字符串数组转换为double数组
	 * 
	 * @param arr
	 * @return
	 */
	private static double[] conventStringToDouble(String[] arr) {
		double[] arr2 = new double[arr.length];
		for (int i = 0; i < arr2.length; i++) {
			arr2[i] = Double.parseDouble(arr[i]);
		}
		return arr2;
	}

	/**
	 * 将字符串数组转化为int 数组
	 * 
	 * @param arr
	 * @return
	 */
	private static int[] conventStringToInt(String[] arr) {
		int[] arr2 = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			arr2[i] = Integer.parseInt(arr[i]);
		}
		return arr2;
	}

	/**
	 * 将字符串数组转化为 byte数组
	 * 
	 * @param arr
	 * @return
	 */
	private static byte[] conventStringToByte(String[] arr) {
		byte[] arr2 = new byte[arr.length];
		for (int i = 0; i < arr.length; i++) {
			arr2[i] = Byte.parseByte(arr[i]);
		}
		return arr2;
	}

	/**
	 * 将字符串数组转化为 short 数组
	 * 
	 * @param arr
	 * @return
	 */
	private static short[] conventStringToShort(String[] arr) {
		short[] arr2 = new short[arr.length];
		for (int i = 0; i < arr.length; i++) {
			arr2[i] = Short.parseShort(arr[i]);
		}
		return arr2;
	}

	/**
	 * 将字符串数组转化为 long 数组
	 * 
	 * @param arr
	 * @return
	 */
	private static long[] conventStringToLong(String[] arr) {
		long[] arr2 = new long[arr.length];
		for (int i = 0; i < arr.length; i++) {
			arr2[i] = Long.parseLong(arr[i]);
		}
		return arr2;
	}

	/**
	 * 将字符串数组转化为 float 数组
	 * 
	 * @param arr
	 * @return
	 */
	private static float[] conventStringToFloat(String[] arr) {
		float[] arr2 = new float[arr.length];
		for (int i = 0; i < arr.length; i++) {
			arr2[i] = Float.parseFloat(arr[i]);
		}
		return arr2;
	}

	/**
	 * 将字符串数组转化为 boolean数组
	 * 
	 * @param arr
	 * @return
	 */
	private static boolean[] conventStringToBoolean(String[] arr) {
		boolean[] arr2 = new boolean[arr.length];
		for (int i = 0; i < arr.length; i++) {
			arr2[i] = Boolean.parseBoolean(arr[i]);
		}
		return arr2;
	}

	/**
	 * 将字符串数组转化为 Date 数组
	 * 
	 * @param arr
	 * @return
	 * @throws ParseException
	 */
	private static Date[] conventStringToDate(String[] arr) throws ParseException {
		Date[] arr2 = new Date[arr.length];
		for (int i = 0; i < arr.length; i++) {
			arr2[i] = format.parse(arr[i]);
		}
		return arr2;
	}
}
